(function (angular) {
    'use strict';
    var menuModule = angular.module('fs.menu');
    //<fs-nav><fs-nav>
    menuModule.directive('fsNav', fsNav);
    //<fs-menu ng-model="vm.menus"><fs-menu>
    menuModule.directive('fsMenu', fsMenu);
    //<fs-menu-items ng-model="items"><fs-menu-items>
    menuModule.directive('fsMenuItems', fsMenuItems);

    fsNav.$inject = ['$timeout', 'storageService', 'MenuConstants'];
    function fsNav($timeout, storageService, MenuConstants) {
        return {
            restrict: 'EA',
            replace: true,
            controller: ['$scope', function ($scope) {
                var ctrl = this, watcher, watchers = [];
                $scope.$on('$destroy', function () {
                    while (watchers.length) {
                        (watchers.shift() || angular.noop)();
                    }
                });
                ctrl.navigationCache = [];
                $scope.$root.buildNav = function (pageId) {
                    var menus, action, missActions, hasMenu, menuKeyPrefix;
                    if (!pageId || (ctrl.currentStateUrl == pageId)) {
                        return;
                    }
                    ctrl.currentStateUrl = pageId;
                    menus = storageService.getMenuConfigInfo();
                    if (ctrl.navigationCache[pageId]) {
                        ctrl.navs = ctrl.navigationCache[pageId];
                    } else {
                        ctrl.navs = [];
                        ctrl.currentStateUrl = ctrl.currentStateUrl.split(".");
                        action = ctrl.currentStateUrl.pop();
                        ctrl.currentStateUrl.push(action);
                        action = action.toUpperCase();
                        ctrl.currentStateUrl = ctrl.currentStateUrl.join('/');
                        hasMenu = buildMenuNav(ctrl.currentStateUrl, menus, ctrl.navs);
                        ctrl.currentStateUrl = ctrl.currentStateUrl.split('/');

                        while (!hasMenu && ctrl.currentStateUrl.length > 2) {
                            if (missActions) {
                                missActions.unshift(ctrl.currentStateUrl.pop().toLowerCase());
                            } else {
                                ctrl.currentStateUrl.pop();
                                missActions = [];
                            }
                            ctrl.currentStateUrl = ctrl.currentStateUrl.join('/');
                            hasMenu = buildMenuNav(ctrl.currentStateUrl, menus, ctrl.navs);
                            ctrl.currentStateUrl = ctrl.currentStateUrl.split('/');
                        }

                        if (!hasMenu && ctrl.currentStateUrl.length <= 2) {
                            ctrl.currentStateUrl = ctrl.currentStateUrl.join('.');
                            if ('waf.home' != ctrl.currentStateUrl) {
                                ctrl.navs.unshift('title.navigation.' + ctrl.currentStateUrl.toLowerCase());
                            }
                        }
                        if (missActions && missActions.length > 0) {
                            angular.forEach(missActions, function (actionCode, index) {
                                menuKeyPrefix = ctrl.navs.length > 0 ? ctrl.navs[0] : 'title.navigation.unkonw';
                                ctrl.navs.unshift(menuKeyPrefix + '.' + actionCode);
                            });
                        }
                        if (ctrl.navs.length > 0 && MenuConstants.NAVIGATION_ACTIONS[action]) {
                            ctrl.navs.unshift(MenuConstants.NAVIGATION_ACTIONS[action]);
                        }
                        if (angular.isArray(ctrl.currentStateUrl)) {
                            ctrl.currentStateUrl = ctrl.currentStateUrl.join('.');
                        }
                        ctrl.navigationCache[pageId] = ctrl.navs.reverse();
                    }

                };

                function buildMenuNav(action, menuItems, navs) {
                    var i = 0;
                    for (i = 0; i < menuItems.length; i++) {
                        if (menuItems[i].actionName && (menuItems[i].actionName + '/').indexOf(action + '/') >= 0) {
                            navs.push(menuItems[i].displayName);
                            return true;
                        } else if (menuItems[i].subMenuItems) {
                            if (buildMenuNav(ctrl.currentStateUrl, menuItems[i].subMenuItems, navs)) {
                                navs.push(menuItems[i].displayName);
                                return true;
                            }
                        }
                    }
                    return false;
                }
            }],
            controllerAs: 'fsNavController',
            link: angular.noop,
            templateUrl: function (element, attrs) {
                return attrs.templateUrl || 'menu/menuNav.html';
            }
        };
    }

    fsMenu.$inject = [];
    function fsMenu() {
        return {
            restrict: 'EA',
            replace: true,
            required: 'uibDropdown',
            controller: function () { },
            link: function ($scope, $element, $attrs, dropdownCtrl, $transclude) {
                var watcher;
                $scope.$on('$destroy', function () {
                    watcher();
                });
                watcher = $scope.$watch($attrs.ngModel, function (newValue, oldValue) {
                    $scope.fsMenu = newValue;
                    angular.forEach($scope.fsMenu, function (value, key) {
                        $scope.fsMenu[key].icon = getIcon($scope.fsMenu[key]);
                        $scope.fsMenu[key].state = value.actionName ? value.actionName.split('/').join('.') : value.actionName;
                    });
                });
                $scope.isCurrent = function (items) {
                    var i, f = false, currentStateName = ($scope.$state && $scope.$state.current) ? $scope.$state.current.name.split('_').join('.') : '';
                    for (i = 0; i < items.length; i++) {
                        if (currentStateName.indexOf(items[i].state) >= 0) {
                            f = true;
                            break;
                        } else if (items[i].subMenuItems) {
                            f = $scope.isCurrent(items[i].subMenuItems);
                        }
                    }
                    return f;
                };
            },
            templateUrl: function (element, attrs) {
                return attrs.templateUrl || 'menu/menuTemplate.html';
            }
        };

        function getIcon(menu) {
            var iconName;
            switch (menu.menuId) {
                case 'm1':
                    iconName = 'workflow';
                    break;
                case 'm2':
                    iconName = 'admin';
                    break;
                case 'm3':
                    iconName = 'data';
                    break;
                case 'm4':
                    iconName = 'ldata';
                    break;
                case 'm5':
                    iconName = 'transaction';
                    break;
                case 'm6':
                    iconName = 'payerables';
                    break;
                case 'm7':
                    iconName = 'document';
                    break;
                case 'm8':
                    iconName = 'tools';
                    break;
                case 'm9':
                    iconName = 'limit';
                    break;
                default:
                    iconName = 'reports';

            }
            return iconName;
        }
    }

    fsMenuItems.$inject = [];
    function fsMenuItems() {
        return {
            restrict: 'EA',
            replace: true,
            required: '^^?uibDropdown',
            controller: function () { },
            controllerAs: 'vm',
            scope: {
                fsMenu: '<ngModel',
                isOpen: '<'
            },
            link: function ($scope, $element, $attr, dropdownCtrl, $transclude) {
                var watchers = [];
                $scope.$on('$destroy', function () {
                    while (watchers.length) {
                        (watchers.shift() || angular.noop)();
                    }
                });
                angular.forEach($scope.fsMenu, function (value, key) {
                    $scope.fsMenu[key].state = value.actionName ? value.actionName.split('/').join('.') : value.actionName;
                });
                $scope.open = function (item) {
                    if (!$scope.isOpen) {
                        item.open = false;
                    }
                    return item.open;
                };
                $scope.toggleDropdown = function ($event, item) {
                    if (!item.actionName) {
                        item.open = !item.open;
                        $event.preventDefault();
                        $event.stopPropagation();
                    } else {
                        $scope.$root.go(item.state, angular.fromJson(item.href));
                    }
                };
            },
            templateUrl: function (element, attrs) {
                return attrs.templateUrl || 'menu/menuItemsTemplate.html';
            }
        };
    }
})(angular);